package com.powernode.driver.service.impl;

import com.powernode.driver.properties.MinioProperties;
import com.powernode.driver.service.FileService;
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 文件服务实现类
 * 负责将文件上传到MinIO对象存储服务
 */
@Slf4j  // 启用日志功能
@Service  // 声明为Spring服务组件
@SuppressWarnings({"unchecked", "rawtypes"})  // 抑制未检查的类型警告
public class FileServiceImpl implements FileService {

    @Resource  // 自动注入MinIO配置属性
    private MinioProperties minioProperties;

    /**
     * 上传文件到MinIO存储服务
     * @param file 要上传的文件对象
     * @return 上传后的文件访问URL
     */
    @Override
    public String upload(MultipartFile file) {
        try {
            // 创建MinIO客户端实例
            MinioClient minioClient = new MinioClient.Builder()
                    .endpoint(minioProperties.getEndpointUrl())  // 设置MinIO服务器地址
                    .credentials(minioProperties.getAccessKey(), minioProperties.getSecreKey())  // 设置访问凭证
                    .build();

            // 检查指定的存储桶是否存在
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());
            // 如果存储桶不存在，则创建新的存储桶
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());
            }

            // 提取文件扩展名
            String extFileName = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
            // 生成唯一的文件名，格式为：日期/UUID.扩展名
            // 这样可以按日期组织文件，并避免文件名冲突
            String fileName = new SimpleDateFormat("yyyyMMdd").format(new Date()) + "/" + UUID.randomUUID().toString().replaceAll("-", "") + extFileName;

            // 构建文件上传参数
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())  // 指定存储桶名称
                    .stream(file.getInputStream(), file.getSize(), -1)  // 设置文件输入流、大小和分块大小(-1表示自动计算)
                    .object(fileName)  // 设置存储在MinIO中的对象名称
                    .build();
            // 执行文件上传操作
            minioClient.putObject(putObjectArgs);

            // 构建并返回文件访问URL
            return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + fileName;
        } catch (Exception e) {
            // 捕获并转换所有异常为运行时异常
            throw new RuntimeException(e);
        }
    }
}
